package com.example.springboot.service.impl;;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springboot.entity.*;
import com.example.springboot.mapper.*;
import com.example.springboot.service.IBookService;
import com.example.springboot.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements IBookService{

    @Autowired
    private CollectMapper collectMapper;

    @Autowired
    private BookMapper bookMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private BorrowMapper borrowMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public boolean save(Book entity) {
        entity.setCreateDate(DateUtil.now());
        return super.save(entity);
    }

    @Override
    public boolean updateById(Book entity) {
        return super.updateById(entity);
    }

    @Override
    public boolean removeById(Book entity) {
        return super.removeById(entity);
    }

    @Override
    public boolean removeBatchByIds(Collection<?> list) {
        return super.removeBatchByIds(list);
    }

    @Override
    public List<Book> list() {
        return super.list();
    }

    @Override
    public Book getById(Serializable id) {
        Book book = super.getById(id);
        User currentUser = TokenUtils.getCurrentUser();
        if (Objects.nonNull(currentUser)){
            // 是否收藏
            Collect collect = collectMapper.selectOne(new LambdaQueryWrapper<Collect>().eq(Collect::getUserId, currentUser.getId()).eq(Collect::getBookId, id));
            if (null == collect) {
                book.setIsCollect(false);
            } else {
                book.setIsCollect(true);
            }
        }
        book.setBorrowCount(borrowMapper.selectCount(new LambdaQueryWrapper<Borrow>().eq(Borrow::getBookId, id)));
        return book;
    }

    @Override
    public <E extends IPage<Book>> E page(E page, Wrapper<Book> queryWrapper) {
        return super.page(page, queryWrapper);
    }

    @Override
    public List<Book> newBook() {
        return super.list(new LambdaQueryWrapper<Book>().eq(Book::getIsShelf,"0").orderByDesc(Book::getCreateDate)).stream().limit(4).collect(Collectors.toList());
    }

    @Override
    public List<Book> hotBook() {
        List<Book> list = super.list(new LambdaQueryWrapper<Book>().eq(Book::getIsShelf,"0"));
        list.stream().forEach(book -> {
            book.setBorrowCount(borrowMapper.selectCount(new LambdaQueryWrapper<Borrow>().eq(Borrow::getBookId, book.getId())));
        });

        List<Book> sortedDesc = list.stream()
                .sorted(Comparator.comparingLong(Book::getBorrowCount).reversed())
                .collect(Collectors.toList());
        return sortedDesc.stream().limit(5).collect(Collectors.toList());
    }

    @Override
    public JSONObject bookCount() {
        List<Category> categories = categoryMapper.selectList(null);
        List<String> x = new ArrayList<>();
        List<Long> y = new ArrayList<>();
        for (Category category: categories){
            x.add(category.getName());
            y.add(bookMapper.selectCount(new LambdaQueryWrapper<Book>().eq(Book::getCategoryId,category.getId())));
        }

        JSONObject result = new JSONObject();
        result.set("x",x);
        result.set("y",y);
        return result;
    }

    @Override
    public List<JSONObject> borrowCount() {
        List<Book> books = bookMapper.selectList(null);

        List<JSONObject> list = new ArrayList<>();
        for (Book book : books) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name",book.getName());
            jsonObject.put("value", borrowMapper.selectCount(new LambdaQueryWrapper<Borrow>().eq(Borrow::getBookId,book.getId())));
            list.add(jsonObject);
        }
        return list;
    }

}
